package com.redhipps.hips.client.widget;

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.redhipps.hips.client.model.DateTime;

/**
 * Simple calendar widget with cell renderer interface.
 * 
 * @author yuhong
 */
public class CalendarView extends Composite {

  private static final String[] DAYS = new String[] { "Sunday", "Monday", "Tuesday",
      "Wednesday", "Thursday", "Friday", "Saturday" };

  private static final String[] MONTHS = new String[] { "January", "February", "March",
      "April", "May", "June", "July", "August", "September", "October",
      "November", "December" };

  private final FlexTable grid;
  private Label header;
  private final DockPanel outer;
  private DateTime dateTime;
  private CalendarCellRenderer cellRenderer;

  public CalendarView(DateTime dateTime, CalendarCellRenderer renderer) {
    this.cellRenderer = renderer;
    setDateTime(dateTime);
    grid = new FlexTable();
    grid.setStyleName("table");
    grid.setCellSpacing(0);
    header = new Label();
    outer = new DockPanel();
    outer.add(header, DockPanel.NORTH);
    outer.add(grid, DockPanel.CENTER);
    initWidget(outer);
    setStyleName("CalendarWidget");
    redraw();
  }

  public void redraw() {
    int year = dateTime.getYear();
    int month = dateTime.getMonth();
    setHeaderText(year, month);
    grid.getRowFormatter().setStyleName(0, "weekheader");
    for (int i = 0; i < DAYS.length; i++) {
      grid.getCellFormatter().setStyleName(0, i, "days");
      grid.setText(0, i, DAYS[i]);
    }

    DateTime now = DateTime.now();
    int sameDay = now.getDay(); 
    int today = (now.getMonth() == month && now.getYear() == year) ? sameDay : 0;
        
    int firstDay = new DateTime(year, month, 1).getDayOfWeek();
    int daysInMonth = DateTime.daysInMonth(year, month);

    int j = 0;
    int rows = (firstDay + daysInMonth) / 7 + 1;
    for (int i = 1; i <= rows; i++) {
      for (int k = 0; k < 7; k++, j++) {
        int displayNum = (j - firstDay + 1);
        if (j < firstDay || displayNum > daysInMonth) {
          grid.getCellFormatter().setStyleName(i, k, "empty");
          grid.setHTML(i, k, "&nbsp;");
        } else {
          Widget panel = cellRenderer.render(new DateTime(year, month, displayNum));
          grid.setWidget(i, k, panel);
          grid.getCellFormatter().setStyleName(i, k, "cell");
          if (displayNum == today) {
            grid.getCellFormatter().addStyleName(i, k, "today");
          } else if (displayNum == sameDay) {
            grid.getCellFormatter().addStyleName(i, k, "day");
          }
        }
      }
    }
  }

  protected void setHeaderText(int year, int month) {
    header.setText(MONTHS[month - 1] + ", " + year);
  }
    
  private void setDateTime(DateTime dateTime) {
    this.dateTime = dateTime;
  }

  public DateTime getDateTime() {
    return dateTime;
  }
}
